#include "httpServer.hpp"

#include <memory>

using namespace Server;

void Usage(std::string proc)
{
    std::cerr << "Usage: \n\t" << proc << " port\r\n"
              << std::endl;
}

std::string suffixToDescrb(const std::string suffix)
{
    std::string ret = "Content-Type: ";
    if (suffix == ".html")
        ret += "text/html";
    else if (suffix == ".png")
        ret += "image/png;application/x-png";
    else if (suffix == ".jpg")
        ret += "application/x-jpg;image/jpeg";

    ret += "\r\n"; // 分隔符

    return ret;
}

bool Get(const httpRequest &req, httpResponse &resp)
{
    // if(req._path == "test.py"/*以test为例*/)// 提交给python脚本执行
    // {
    //     // 1. 建立进程间通信，如管道
    //
    //     // 2. 创建子进程，进程替换，子进程执行如"/bin/python", test.py这样的脚本
    //
    //     // 3. 父进程，通过管道（对照1.）将req._param写给某些后端语言如python，java，php，go等
    //
    //     // 这就是为什么有的服务器是用C++写的，但其使用的后端语言却是其他语言而非C++
    //     // 这也是为什么前端提交资源时，要通过action指定要提交给谁
    // }
    // if(req._path == "/search"/*以此搜索路径为例*/)
    // {
    //     // 已知参数: req._param
    //
    //     // 使用自己用C++写的方法来提供服务
    // }

    std::cout << "----------------http request-----------------" << std::endl;
    std::cout << req._inBuffer; // 暂时不做处理
    std::cout << "method: " << req._method << std::endl;
    std::cout << "url: " << req._url << std::endl;
    std::cout << "version: " << req._version << std::endl;
    std::cout << "path: " << req._path << std::endl;
    std::cout << "suffix: " << req._suffix << std::endl;
    std::cout << "size: " << req._size << "字节" << std::endl;
    std::cout << "----------------http request done-----------------\n"
              << std::endl;

    // 从文件中读取正文
    std::string body;
    body.resize(req._size);// 这里"+1"是因为要适应string机制，可能会有'\0'。但因为读取的是二进制数据，所以"+1"按理说应该可以不要，本机适于此种情况，无需"+1"
    if (!util::readFile(req._path, (char *)body.c_str(), body.size())) // 读取失败
    {
        // std::cout << "readFile fail" << std::endl;
        // body.clear();
        // util::readFile(page_404, &body); // 认为此操作一定成功
        util::readFile(page_404, (char *)body.c_str(), body.size());
    }

    // 生成响应
    std::string respLine = "HTTP/1.1 200 OK\r\n"; // 响应行
    // std::string respLine = "HTTP/1.1 307 Tempory Redirect\r\n"; // 响应行
    // std::string respHead = "Content-Type: text/html\r\n";
    std::string respHead = suffixToDescrb(req._suffix);
    // if (req._size > 0)
    // {
    //     respHead += "Content-Length: ";
    //     respHead += std::to_string(req._size);
    //     respHead += "\r\n";
    // }
    if (req._size > 0) // 资源存在，设置长度
    {
        respHead += "Content-Length: ";
        respHead += std::to_string(body.size());// 需要是正文的大小
        respHead += "\r\n";
    }

    // respHead += "Location: https://www.baidu.com/\r\n";// 重定向使用

    respHead += "Set-Cookie: name=test123456abc; Max-Age=120\r\n"; // Max-Age单位：秒
    // 设置完cookie后，往后每次http请求都会自动携带曾经设置的所有有效的cookie，来帮助服务器进行鉴权行为——http会话保持

    std::string respBlank = "\r\n"; // 响应空行

    resp._outBuffer += respLine;
    resp._outBuffer += respHead;
    resp._outBuffer += respBlank;

    std::cout << "----------------http response-----------------" << std::endl;
    std::cout << resp._outBuffer;
    std::cout << "----------------http response done-----------------\n"
              << std::endl;

    resp._outBuffer += body;

    return true;
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(0);
    }

    uint16_t port = std::atoi(argv[1]);
    std::unique_ptr<httpServer> uhs(new httpServer(Get, port));

    // 根据请求路径绑定服务方法——这就是http的功能路由！
    // uhs->registercb("/", Get);// 根目录执行Get方法
    // uhs->registercb("/search", Search);// test
    // uhs->registercb("/test.py", Topython);// test

    uhs->init();
    uhs->start();

    return 0;
}